{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": [],
      "authorship_tag": "ABX9TyP3f0+ueKPgrKhFpzZWRC4C",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/sugarforever/LangChain-Advanced/blob/main/langchain_with_openai_assistants_api.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# OpenAI Assistants API with LangChain\n",
        "\n",
        "OpenAI finally released the **Assistants** API. It allows users to build AI assistants within the applications.\n",
        "\n",
        "An Assistant has instructions and can leverage models, tools, and knowledge to respond to user queries. The **Assistants** API currently supports three types of tools:\n",
        "- Code Interpreter\n",
        "- Retrieval\n",
        "- Function calling\n",
        "\n",
        "In this tutorial, I will share with you 2 ways of using **Assistants** API:\n",
        "\n",
        "1. Command line tool `curl`\n",
        "2. `LangChain`\n",
        "\n",
        "You can surely use the official OpenAI Python SDK. It's just not covered in this tutorial.\n",
        "\n",
        "In principle, to interact with an Assistant, the following steps should be followed:\n",
        "\n",
        "1. Create an `Assistant`\n",
        "2. Create a `Thread`\n",
        "3. Submit a `Run`\n",
        "4. Query the `Run` status\n",
        "5. Retrieve the `Assistant`'s response (message)"
      ],
      "metadata": {
        "id": "ykElVnxqDNO7"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Play with `curl`\n",
        "\n",
        "Before you run the following commands, make sure you have a valid **OPENAI_API_KEY** environmental variable set."
      ],
      "metadata": {
        "id": "bpPPGpeuE3wj"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "### 1. Create an Assistant\n",
        "\n",
        "```shell\n",
        "curl \"https://api.openai.com/v1/assistants\" \\\n",
        "  -u:$OPENAI_API_KEY \\\n",
        "  -H \"Content-Type: application/json\" \\\n",
        "  -H \"OpenAI-Beta: assistants=v1\" \\\n",
        "  -d '{\n",
        "    \"instructions\": \"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n",
        "    \"name\": \"Math Tutor\",\n",
        "    \"tools\": [{\"type\": \"code_interpreter\"}],\n",
        "    \"model\": \"gpt-4\"\n",
        "  }'\n",
        "```\n",
        "\n",
        "You will be given an assistant id in this API response.\n",
        "\n",
        "```json\n",
        "{\n",
        "  \"id\": \"asst_M1qNqUsUIeItZ8f7JG6FLHTy\",\n",
        "  \"object\": \"assistant\",\n",
        "  \"created_at\": 1699486594,\n",
        "  \"name\": \"Math Tutor\",\n",
        "  \"description\": null,\n",
        "  \"model\": \"gpt-4\",\n",
        "  \"instructions\": \"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n",
        "  \"tools\": [\n",
        "    {\n",
        "      \"type\": \"code_interpreter\"\n",
        "    }\n",
        "  ],\n",
        "  \"file_ids\": [],\n",
        "  \"metadata\": {}\n",
        "}%         \n",
        "```\n",
        "\n",
        "### 2. Create a Thread\n",
        "\n",
        "A `Thread` represents a conversation between an Assistant and a user.\n",
        "\n",
        "```shell\n",
        "curl https://api.openai.com/v1/threads \\\n",
        "  -u:$OPENAI_API_KEY \\\n",
        "  -H 'Content-Type: application/json' \\\n",
        "  -H 'OpenAI-Beta: assistants=v1' \\\n",
        "  -d '{\n",
        "    \"messages\": [\n",
        "      {\n",
        "          \"role\": \"user\",\n",
        "          \"content\": \"Work out the sum of 1, 2 and 3\"\n",
        "      }\n",
        "    ]\n",
        "  }'\n",
        "```\n",
        "\n",
        "You will be given a Thread id in this API response.\n",
        "\n",
        "```json\n",
        "{\n",
        "  \"id\": \"thread_lEH83Q4bKV3hv4Y9yECcjfgy\",\n",
        "  \"object\": \"thread\",\n",
        "  \"created_at\": 1699486702,\n",
        "  \"metadata\": {}\n",
        "}\n",
        "```\n",
        "\n",
        "### 3. Submit a Run\n",
        "\n",
        "Submit a Run with the `thread id` and `assistant id` to `run` the conversation.\n",
        "\n",
        "```shell\n",
        "curl https://api.openai.com/v1/threads/<thread_id>/runs \\\n",
        "  -u:$OPENAI_API_KEY \\\n",
        "  -H 'Content-Type: application/json' \\\n",
        "  -H 'OpenAI-Beta: assistants=v1' \\\n",
        "  -d '{\n",
        "    \"assistant_id\": \"asst_M1qNqUsUIeItZ8f7JG6FLHTy\"\n",
        "  }'\n",
        "```\n",
        "\n",
        "You will be given a Run id in this API response.\n",
        "\n",
        "```json\n",
        "{\n",
        "  \"id\": \"run_in35OoYZNo0osZnQOQrAHaNo\",\n",
        "  \"object\": \"thread.run\",\n",
        "  \"created_at\": 1699486777,\n",
        "  \"assistant_id\": \"asst_M1qNqUsUIeItZ8f7JG6FLHTy\",\n",
        "  \"thread_id\": \"thread_lEH83Q4bKV3hv4Y9yECcjfgy\",\n",
        "  \"status\": \"queued\",\n",
        "  \"started_at\": null,\n",
        "  \"expires_at\": 1699487377,\n",
        "  \"cancelled_at\": null,\n",
        "  \"failed_at\": null,\n",
        "  \"completed_at\": null,\n",
        "  \"last_error\": null,\n",
        "  \"model\": \"gpt-4\",\n",
        "  \"instructions\": \"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n",
        "  \"tools\": [\n",
        "    {\n",
        "      \"type\": \"code_interpreter\"\n",
        "    }\n",
        "  ],\n",
        "  \"file_ids\": [],\n",
        "  \"metadata\": {}\n",
        "}\n",
        "```\n",
        "\n",
        "### 4. Query the Run status\n",
        "\n",
        "```shell\n",
        "curl https://api.openai.com/v1/threads/<thread_id>/runs/<run_id> \\\n",
        "  -u:$OPENAI_API_KEY \\\n",
        "  -H 'OpenAI-Beta: assistants=v1'\n",
        "```\n",
        "\n",
        "You will see the status of the Run in the API response.\n",
        "\n",
        "```json\n",
        "{\n",
        "  \"id\": \"run_in35OoYZNo0osZnQOQrAHaNo\",\n",
        "  \"object\": \"thread.run\",\n",
        "  \"created_at\": 1699486777,\n",
        "  \"assistant_id\": \"asst_M1qNqUsUIeItZ8f7JG6FLHTy\",\n",
        "  \"thread_id\": \"thread_lEH83Q4bKV3hv4Y9yECcjfgy\",\n",
        "  \"status\": \"completed\",\n",
        "  \"started_at\": 1699486777,\n",
        "  \"expires_at\": null,\n",
        "  \"cancelled_at\": null,\n",
        "  \"failed_at\": null,\n",
        "  \"completed_at\": 1699486783,\n",
        "  \"last_error\": null,\n",
        "  \"model\": \"gpt-4\",\n",
        "  \"instructions\": \"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n",
        "  \"tools\": [\n",
        "    {\n",
        "      \"type\": \"code_interpreter\"\n",
        "    }\n",
        "  ],\n",
        "  \"file_ids\": [],\n",
        "  \"metadata\": {}\n",
        "}%\n",
        "```\n",
        "\n",
        "### 5. Retrieve the Assistant's response\n",
        "\n",
        "The Assistant's response will be the latest message in the following API response:\n",
        "\n",
        "```shell\n",
        "curl https://api.openai.com/v1/threads/<thread_id>/messages \\\n",
        "  -u:$OPENAI_API_KEY \\\n",
        "  -H \"Content-Type: application/json\" \\\n",
        "  -H \"OpenAI-Beta: assistants=v1\"\n",
        "```\n",
        "\n",
        "Sample response:\n",
        "\n",
        "```json\n",
        "{\n",
        "  \"object\": \"list\",\n",
        "  \"data\": [\n",
        "    {\n",
        "      \"id\": \"msg_bCgflETMYexEUEGqHkwNgN6Z\",\n",
        "      \"object\": \"thread.message\",\n",
        "      \"created_at\": 1699486782,\n",
        "      \"thread_id\": \"thread_lEH83Q4bKV3hv4Y9yECcjfgy\",\n",
        "      \"role\": \"assistant\",\n",
        "      \"content\": [\n",
        "        {\n",
        "          \"type\": \"text\",\n",
        "          \"text\": {\n",
        "            \"value\": \"The sum of 1, 2, and 3 is 6.\",\n",
        "            \"annotations\": []\n",
        "          }\n",
        "        }\n",
        "      ],\n",
        "      \"file_ids\": [],\n",
        "      \"assistant_id\": \"asst_M1qNqUsUIeItZ8f7JG6FLHTy\",\n",
        "      \"run_id\": \"run_in35OoYZNo0osZnQOQrAHaNo\",\n",
        "      \"metadata\": {}\n",
        "    },\n",
        "    {\n",
        "      \"id\": \"msg_I4xv8bsfy5evvEC8K4MVZar3\",\n",
        "      \"object\": \"thread.message\",\n",
        "      \"created_at\": 1699486702,\n",
        "      \"thread_id\": \"thread_lEH83Q4bKV3hv4Y9yECcjfgy\",\n",
        "      \"role\": \"user\",\n",
        "      \"content\": [\n",
        "        {\n",
        "          \"type\": \"text\",\n",
        "          \"text\": {\n",
        "            \"value\": \"Work out the sum of 1, 2 and 3\",\n",
        "            \"annotations\": []\n",
        "          }\n",
        "        }\n",
        "      ],\n",
        "      \"file_ids\": [],\n",
        "      \"assistant_id\": null,\n",
        "      \"run_id\": null,\n",
        "      \"metadata\": {}\n",
        "    }\n",
        "  ],\n",
        "  \"first_id\": \"msg_bCgflETMYexEUEGqHkwNgN6Z\",\n",
        "  \"last_id\": \"msg_I4xv8bsfy5evvEC8K4MVZar3\",\n",
        "  \"has_more\": false\n",
        "}%\n",
        "```"
      ],
      "metadata": {
        "id": "CgoXjB6bFgUZ"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Play with LangChain\n",
        "\n",
        "LangChain dev team has been responding to OpenAI changes proactively. The latest **RC** version of LangChain has already supported **Assistants** API.\n",
        "\n",
        "Make sure you use at least version `0.0.331rc2` of LangChain to work with Assistants API.\n",
        "\n",
        "Currently LangChain is delivering the Assistants support by `langchain-experimental` package.\n",
        "\n",
        "The only class you need is just **OpenAIAssistantRunnable**, which makes code much cleaner.\n",
        "\n",
        "Let's see below."
      ],
      "metadata": {
        "id": "1BVbUSW2IC51"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "import os\n",
        "os.environ[\"OPENAI_API_KEY\"] = 'your valid OpenAI API key with GPT-4 enabled'"
      ],
      "metadata": {
        "id": "GjlOblb38jmA"
      },
      "execution_count": 17,
      "outputs": []
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "em823NSa5xOa"
      },
      "outputs": [],
      "source": [
        "!pip install -U -q \"langchain==0.0.331rc2\" langchain-experimental \"openai>=1.1\""
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain_experimental.openai_assistant import OpenAIAssistantRunnable"
      ],
      "metadata": {
        "id": "4vxoGs1DBVnX"
      },
      "execution_count": 14,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "interpreter_assistant = OpenAIAssistantRunnable.create_assistant(\n",
        "    name=\"langchain assistant\",\n",
        "    instructions=\"You are a personal math tutor. When asked a question, write and run Python code to answer the question.\",\n",
        "    tools=[{\"type\": \"code_interpreter\"}],\n",
        "    model=\"gpt-4\"\n",
        ")"
      ],
      "metadata": {
        "id": "RvPrTrT3Cy6z"
      },
      "execution_count": 18,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "output = interpreter_assistant.invoke({\"content\": \"Work out the sum of 1, 2 and 3\"})\n",
        "output"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "us5FDeYi8a25",
        "outputId": "bb930f15-9d8b-4f89-a3fa-b7c02a1ec0f1"
      },
      "execution_count": 19,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[ThreadMessage(id='msg_RnANxbiBnHsm08qNLOZiMLgX', assistant_id='asst_ZYhTHQEq3oxx9EM8a7TyE4Ac', content=[MessageContentText(text=Text(annotations=[], value='The sum of 1, 2 and 3 is 6.'), type='text')], created_at=1699487072, file_ids=[], metadata={}, object='thread.message', role='assistant', run_id='run_x9f7CXuvuAKGbGwGktLf1ghY', thread_id='thread_Fe5tZZGTBhJShOaBPDAbqOjz')]"
            ]
          },
          "metadata": {},
          "execution_count": 19
        }
      ]
    }
  ]
}